package controllers.wechatlab;

import java.beans.PropertyDescriptor;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.druid.stat.JdbcConnectionStat.Entry;

import cn.edu.bjtu.alex.hotswap.TextCateClassLoader;
import cn.edu.bjtu.alex.rewrite.Context;
import cn.edu.bjtu.alex.rewrite.LibSVMDriver;
import cn.edu.bjtu.alex.rewrite.StatDriver;
import cn.edu.bjtu.alex.rewrite.TrainDriver;
import cn.edu.bjtu.alex.rewrite.TransformDriver;
import pojo.ResCode;
import pojo.weichatlab.model.Document;
import pojo.weichatlab.model.LabelDocTermDTO;
import service.wechatlab.impl.CompoundTestService;
import util.docparser.impl.HiveWechatParser;
import util.docparser.impl.LineParser;
import util.docparser.interfaces.Parser;



@Controller
@RequestMapping(value="fp")
//RequestMapping是一个用来处理请求地址映射的注解，可用于类或方法上。用于类上，表示类中的所有响应请求的方法都是以该地址作为父路径。
public class FeatureProjectController extends WechatBaseController{
	
	private File pathOut = new File(getAppProperties("dataset_out"));
	private File pathIn = new File(getAppProperties("dataset_dir"));
	Context ctx = new Context(getAppProperties("dataset_dir"),getAppProperties("dataset_out"));
	
	Parser sp = new HiveWechatParser();	
	Parser lp = new LineParser();	
	
	@RequestMapping(value="/index.do")
	public ModelAndView index(HttpServletRequest req,HttpServletResponse res) throws IOException{
		int totalDoc = ctx.getTotalDocCount();	
		if(totalDoc == 0){
			//context为空
			return renderView("fp/index",null).addObject("isExist",false);
		}else{
			return renderView("fp/index",null).addObject("isExist",true).addObject("totalDoc",totalDoc).addObject("eachClassCount",new LabelDocTermDTO(ctx.termTableIterator()));
		}
	}
	@RequestMapping(value="/handlefs.do")
	@ResponseBody
	public String handleFile(HttpServletRequest req,HttpServletResponse res) throws IOException{
		String action = req.getParameter("action");
		String param = req.getParameter("arg");
		if(StringUtils.hasText(action)){
			File f = ctx.getInputDir();
			File target = new File (f,param);
			switch(action){
			case"mkdir":
				if(target.exists()){
					return jsonDump(SUCCESS);
				}else{
					target.mkdirs();
					target.setExecutable(true);
					target.setWritable(true);
					target.setReadable(true);
					return jsonDump(SUCCESS);
				}
			case"rmdir":
				if(!target.exists()){
					return jsonDump(SUCCESS);
				}else{
					boolean result = deleteFSRec(target);
					return result?jsonDump(SUCCESS):jsonDump(ERROR);
				}
				
			default:
					
			}
		}
		return jsonDump(ERROR);
	}
	
	private boolean deleteFSRec(File f){
		if(f.exists() && f.isDirectory()){
			boolean flag = true;
			File[] subfiles = f.listFiles();
			for(File sf:subfiles){
				flag &= deleteFSRec(sf);
			}
			if(flag) f.delete();
			return flag;
		}else if(f.exists() && !f.isDirectory()){
			return f.delete();
		}else{
			return true;
		}
	}
	
	@RequestMapping(value="/tfidf.do")
	public ModelAndView tfidf(HttpServletRequest req,HttpServletResponse res) throws IOException{
		return renderView("fp/tfidf",null).addObject("isExist",true);
	}
	@RequestMapping(value="/fpadmin.do")
	public ModelAndView tfadmin(HttpServletRequest req,HttpServletResponse res) throws IOException{
		Context ctx = new Context(getAppProperties("dataset_dir"),getAppProperties("dataset_out"));
		StatDriver sd = new StatDriver(ctx);
		sd.fit();
		return renderView("fp/admin",null).addObject("isExist",true).addObject("totalDoc",sd.getTotalDoc()).addObject("eachClassCount",sd);
	}
	
	@RequestMapping(value="/train.do")
	public ModelAndView tfidfmodel(HttpServletRequest req,HttpServletResponse res) throws IOException{
			if(ctx.getInputDir().exists() && ctx.getOutputDir().exists()){
				new TrainDriver(ctx).fit();
				int totalDoc = ctx.getTotalDocCount();
				return renderView("fp/index",null).addObject("isExist",true).addObject("totalDoc",totalDoc).addObject("eachClassCount",new LabelDocTermDTO(ctx.termTableIterator()));
			}else{
				return renderView("fp/index",null).addObject("isExist",false).addObject("message","请检查数据集存放目录及模型输出目录!!!");
			}
	}
	
	@RequestMapping(value="/trans.do")
	public void transform(@RequestParam(value="file",required=false) CommonsMultipartFile files[] ,HttpServletRequest req,HttpServletResponse res) throws IOException{
		ctx.setOs(res.getOutputStream());
		if(files == null || files.length == 0){
			res.setHeader("content-type","text/html;charset=utf-8");
			String content = (String)req.getParameter("text");
			ctx.addTransformDocument(lp.parse(content));
			new TransformDriver(ctx).transform();
			return ;
		}else{
			res.setCharacterEncoding("utf-8");
			res.setContentType("multipart/form-data");
			res.setHeader("Content-Disposition", "attachment;fileName=transformed.txt");
			BufferedReader br = new BufferedReader(new InputStreamReader(files[0].getInputStream(),"utf-8")); 
			String line = "";
			while((line = br.readLine())!=null){
				ctx.addTransformDocument(sp.parse(line));
			}
			new LibSVMDriver(ctx).transform();
			return ;
		}
	}
	@RequestMapping(value="/ctxIntrospect.do")
	public ModelAndView introspectModel(HttpServletRequest req,HttpServletResponse res) throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		String fieldName = req.getParameter("field");
		Object v = ERROR;
		if(fieldName == null || fieldName.length()==0)
		{
			return renderView("fp/ShowData",null).addObject("isExist",false);
		}
		else
		{//获取类的属性，不是成员变量
			PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(Context.class, fieldName);
//			System.out.println(pd);
			if(pd!=null)
			{
				String name=pd.getPropertyType().getName().toString();
				String ty=".Map";
				String ty2=".Set";
				v = pd.getReadMethod().invoke(this.ctx, null);
				Set keys1;
				ArrayList  strArray = new ArrayList(); 
				strArray.clear();
				int i=0;
				Iterator Fit=Collections.emptyIterator();
				Iterator Sit=Collections.emptyIterator();
				Iterator Sit2=Collections.emptyIterator();
				if(name.endsWith(ty)){
					keys1 = ((HashMap) v).entrySet();
					Fit = keys1.iterator();
					strArray=getAll(Fit,strArray);
					return renderView("fp/ShowData",null).addObject("isExist",true).addObject("result1",v).addObject("isMap",true).addObject("isSet",false).addObject("isMapAndSet",true).addObject("name",fieldName).addObject("keyset",strArray);
				}
				else if(name.endsWith(ty2)){
					Fit = ((HashSet) v).iterator();
						while(Fit.hasNext()) 
							{   
								strArray.add(Fit.next());           
							}
				    return renderView("fp/ShowData",null).addObject("isExist",true).addObject("result1",v).addObject("isSet",true).addObject("isMap",false).addObject("isMapAndSet",true).addObject("name",fieldName).addObject("keyset",strArray);
				}
				else{
					return renderView("fp/ShowData",null).addObject("isExist",true).addObject("isMap",false).addObject("isSet",false).addObject("result",v).addObject("isMapAndSet",false);
				}
			}
			else{
					return renderView("fp/ShowData",null).addObject("isExist",false);
				}		
			}
		}
	public ArrayList getAll(Iterator a,ArrayList strArray){
		while(a.hasNext()) 
		{ 
			Map.Entry entry = (Map.Entry) a.next();
			strArray.add(entry.getKey());
		    if((entry.getValue()).getClass().toString().endsWith(".HashMap")){
		    	Iterator Sit=((HashMap)(entry.getValue())).entrySet().iterator();
		    	getAll(Sit,strArray);
		    }
		    else{
		    	strArray.add(entry.getValue());
		    }
		}
	    return    strArray;   
	}
	@RequestMapping(value="/upload.do")
	@ResponseBody
	public String upload(@RequestParam("file") CommonsMultipartFile files[], HttpServletRequest req,HttpServletResponse res) throws IOException{
		String subdir = req.getParameter("subdir");
		String out = ctx.getInputDirString();
		File o = new File(out,subdir);
		if(StringUtils.hasText(subdir)){
			int k = 0;
			for(CommonsMultipartFile file :files){
				try{
				FileUtils.copyInputStreamToFile(file.getInputStream(), new File(o,file.getOriginalFilename()));
				k++;
				}catch(Exception e){
					e.printStackTrace();
				}
			}
			return jsonDump(SUCCESS);
		}
		return jsonDump(ParamsError);
	}
	@RequestMapping(value="/download.do")
	@ResponseBody
	public void download(@RequestParam("filename") String filename,HttpServletRequest req,HttpServletResponse res) throws IOException{
		//注意java.io.File类的应用,这个类可以处理不同环境下的文件分割符问题
		File targetFile = new File(ctx.getOutputDirString(),filename);
		
		res.setCharacterEncoding("utf-8");
		res.setContentType("multipart/form-data");
		res.setHeader("Content-Disposition", "attachment;fileName="+filename);
		
		try {
			FileUtils.copyFile(targetFile, res.getOutputStream());
		} catch (Exception e) {
			e.printStackTrace(res.getWriter());
		}
		
		return;
	}
	

	
}
